home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / snpd9611.zip / CMTPARSR.CPP < prev    next >
C/C++ Source or Header  |  1996-11-24  |  7KB  |  309 lines

  1. // +++Date last modified: 02-Aug-1996
  2.  
  3. /*
  4.  * CMTPARSR.CPP
  5.  * Implementation of the comment parser.
  6.  *
  7.  * ver 1.0, 30 Jun 1996
  8.  *
  9.  * Public domain by:
  10.  *   Jari Laaksonen
  11.  *   Arkkitehdinkatu 30 A 2
  12.  *   FIN-33720 Tampere
  13.  *   FINLAND
  14.  *
  15.  *   Fidonet : 2:221/360.20
  16.  *   Internet: jla@to.icl.fi
  17.  */
  18.  
  19. #include <string.h>
  20.  
  21. #include "cmtparsr.h"
  22.  
  23. static  char    CannotOpen[] = "Cannot open %s for %sput\n\n";
  24.  
  25. /* CommentParser::Init
  26.  *   Initialization function which takes the program's command line
  27.  *   arguments and opens the input file and optionally the output file.
  28.  */
  29. int CommentParser::Init (int argc, char **argv)
  30. {
  31.     if (argc < 2)
  32.     {
  33.         return 0;
  34.     }
  35.  
  36.     if (0 == Init (argv[1]))
  37.     {
  38.         return 0;
  39.     }
  40.  
  41.     if (argc == 3)
  42.     {
  43.         if (stricmp (argv[1], argv[2]) == 0)
  44.         {
  45.             // input and output files cannot be the same,
  46.             // output goes to stdout instead.
  47.             OutFile = stdout;
  48.         }
  49.         else if ((OutFile = fopen (argv[2], "w")) == NULL)
  50.         {
  51.             fprintf (stderr, CannotOpen, argv[2], "out");
  52.             // if cannot open, output goes to stdout instead.
  53.             OutFile = stdout;
  54.         }
  55.     }
  56.  
  57.     arguments = argc;
  58.  
  59.     return 1;
  60. }
  61.  
  62. /* CommentParser::Init
  63.  *   Initialization function which opens the input file.
  64.  *   Action processors that don't need output file can use this function.
  65.  */
  66. int CommentParser::Init (char *file)
  67. {
  68.     OutFile = stdout;
  69.  
  70.     if ((InFile = fopen (file, "r")) == NULL)
  71.     {
  72.         fprintf (stderr, CannotOpen, file, "in");
  73.         return 0;
  74.     }
  75.  
  76.     arguments = 2;
  77.  
  78.     return 1;
  79. }
  80.  
  81. /* CommentParser::Uninit
  82.  *  Closes input and output files.
  83.  */
  84. void CommentParser::Uninit()
  85. {
  86.     if (arguments == 3)
  87.         fclose (OutFile);
  88.     fclose (InFile);
  89.  
  90.     fflush (stdout);
  91. }
  92.  
  93. /* CommentParser::ProcessState
  94.  *  The heart of the comment parser. A finite state machine which does
  95.  *  nothing else than determines the current state based on the events.
  96.  */
  97. void CommentParser::ProcessState (Event theEvent)
  98. {
  99.     if (itsState != InsideEscape)
  100.         itsPrevState = itsState;
  101.  
  102.     if (theEvent == FOUND_BACKSLASH)           // Escaped character.
  103.     {
  104.         itsState = InsideEscape;
  105.         return;
  106.     }
  107.  
  108.     switch (itsState)
  109.     {
  110.     case NormalInput:
  111.         switch (theEvent)
  112.         {
  113.         case FOUND_QUOTE:
  114.             itsState = InsideString;
  115.             break;
  116.  
  117.         case FOUND_SINGLEQUOTE:
  118.             itsState = InsideChar;
  119.             break;
  120.  
  121.         case FOUND_SLASH:
  122.             itsState = BeginComment;  // to be investigated: begin of comment.
  123.             break;
  124.         }
  125.         break;
  126.  
  127.     case InsideString:
  128.         switch (theEvent)
  129.         {
  130.         case FOUND_QUOTE:
  131.             itsState = NormalInput;     // End of the string.
  132.             break;
  133.         }
  134.         break;
  135.  
  136.     case InsideChar:
  137.         switch (theEvent)
  138.         {
  139.         case FOUND_SINGLEQUOTE:
  140.             itsState = NormalInput;     // End of the character constant.
  141.             break;
  142.         }
  143.         break;
  144.  
  145.     // We have found a '/', maybe this is a comment...
  146.     case BeginComment:
  147.         switch (theEvent)
  148.         {
  149.         case FOUND_SLASH:
  150.             itsState = InCppComment;    // Yes, it's a C++ comment.
  151.             break;
  152.  
  153.         case FOUND_STAR:
  154.             itsState = InCComment;      // Yes, it's a C comment.
  155.             break;
  156.  
  157.         default:
  158.             itsState = NormalInput;     // No, just a slash.
  159.             break;
  160.         }
  161.         break;
  162.  
  163.     case InsideEscape:
  164.         itsState = itsPrevState;  // Found backslash -- restore previous state.
  165.         break;
  166.  
  167.     case InCppComment:
  168.         switch (theEvent)
  169.         {
  170.         case FOUND_NL:
  171.             itsState = NormalInput;     // Newline is end of C++ comment.
  172.             break;
  173.  
  174.         case FOUND_STAR:
  175.             itsState = StarInCppComment;
  176.             break;
  177.         }
  178.         break;
  179.  
  180.     case InCComment:
  181.         switch (theEvent)
  182.         {
  183.         case FOUND_STAR:
  184.             itsState = StarInCComment;  // to be investigated: end of comment.
  185.             break;
  186.         }
  187.         break;
  188.  
  189.     // '*' in C++ comment: action processors can use this to check
  190.     // e.g. C comments inside C++ comment.
  191.     case StarInCppComment:
  192.         switch (theEvent)
  193.         {
  194.         case FOUND_STAR:
  195.             itsState = StarInCppComment; // another '*' -- don't change state.
  196.             break;
  197.  
  198.         default:
  199.             itsState = InCppComment;
  200.             break;
  201.         }
  202.         break;
  203.  
  204.     // We are inside a C comment, and there is a '*';
  205.     // maybe this is the end of the comment...
  206.     case StarInCComment:
  207.         switch (theEvent)
  208.         {
  209.         case FOUND_STAR:
  210.             itsState = StarInCComment;  // another '*' -- don't change state.
  211.             break;
  212.  
  213.         case FOUND_SLASH:
  214.             itsState = NormalInput;     // Yes, it's end of the C comment.
  215.             break;
  216.  
  217.         default:
  218.             itsState = InCComment;      // No, we are still in C comment.
  219.             break;
  220.         }
  221.         break;
  222.     }
  223. }
  224.  
  225. /* CommentParser::GetEvent
  226.  *  Selects the next event according to the read character.
  227.  */
  228. CommentParser::Event CommentParser::GetEvent()
  229. {
  230.     switch (ReadCh)
  231.     {
  232.     case ' ':
  233.     case '\t':
  234.         return FOUND_WHITESPACE;
  235.  
  236.     case '\"':
  237.         return FOUND_QUOTE;
  238.  
  239.     case '\'':
  240.         return FOUND_SINGLEQUOTE;
  241.  
  242.     case '\\':
  243.         return FOUND_BACKSLASH;
  244.  
  245.     case '\n':
  246.         lines++;          // count processed lines, if someone needs it...
  247.         return FOUND_NL;
  248.  
  249.     case '/':
  250.         return FOUND_SLASH;
  251.  
  252.     case '*':
  253.         return FOUND_STAR;
  254.  
  255.     default:
  256.         return ANY_CHAR;
  257.     }
  258. }
  259.  
  260. /* CommentParser::ReadChar
  261.  *  Read character from input file.
  262.  */
  263. int CommentParser::ReadChar()
  264. {
  265.     ReadCh = fgetc (InFile);
  266.     return ReadCh;
  267. }
  268.  
  269. /* CommentParser::PrintChar
  270.  *  Print current character which can be the last read from the input file
  271.  *  or changed by the action processor.
  272.  */
  273. void CommentParser::PrintChar()
  274. {
  275.     if (ReadCh != EOF)
  276.         fputc (ReadCh, OutFile);
  277. }
  278.  
  279. /* CommentParser::PrintLineNumber
  280.  *  Print current line number.
  281.  */
  282. void CommentParser::PrintLineNumber()
  283. {
  284.     fprintf (OutFile, "\n%05lu:\n", lines);
  285. }
  286.  
  287. /* CommentParser::Run
  288.  *  Loop that reads the input file and calls the action processor and
  289.  *  the state processor.
  290.  */
  291. int CommentParser::Run()
  292. {
  293.     Event theEvent;
  294.  
  295.     while (ReadChar() != EOF)
  296.     {
  297.         theEvent = GetEvent();
  298.         ProcessActions (theEvent);
  299.         ProcessState (theEvent);
  300.     }
  301.  
  302.     // Some action processors may need to do some extra processing
  303.     // based on the state of the FSM after the file is processed.
  304.     ProcessActions (END_OF_FILE);
  305.  
  306.     return 0;
  307. }
  308.  
  309.